package cn.iocoder.yudao.module.system.service.user;

import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.scores.UserScoresExportReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.scores.UserScoresPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.scores.UserScoresSaveReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.UserScoresDO;
import cn.iocoder.yudao.module.system.dal.mysql.user.UserScoresMapper;
import cn.iocoder.yudao.module.system.enums.ErrorCodeConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;

/**
 * 用户成绩 Service 实现类
 *
 * @author 芋道源码
 */
@Service
@Validated
@Slf4j
public class UserScoresServiceImpl implements UserScoresService {

    @Resource
    private UserScoresMapper userScoresMapper;

    @Resource
    private AdminUserService adminUserService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createUserScores(@Valid UserScoresDO userScores) {
        // 如果设置为当前使用的成绩，需要先将该用户的其他成绩设置为非当前
        if (Boolean.TRUE.equals(userScores.getIsCurrent())) {
            userScoresMapper.updateAllToNonCurrent(userScores.getUserId());
        }
        
        userScoresMapper.insert(userScores);
        return userScores.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUserScores(@Valid UserScoresDO userScores) {
        // 校验存在
        validateUserScoresExists(userScores.getId());
        
        // 如果设置为当前使用的成绩，需要先将该用户的其他成绩设置为非当前
        if (Boolean.TRUE.equals(userScores.getIsCurrent())) {
            userScoresMapper.updateAllToNonCurrent(userScores.getUserId());
        }
        
        userScoresMapper.updateById(userScores);
    }

    @Override
    public void deleteUserScores(Long id) {
        // 校验存在
        validateUserScoresExists(id);
        
        userScoresMapper.deleteById(id);
    }

    @Override
    public UserScoresDO getUserScores(Long id) {
        return userScoresMapper.selectById(id);
    }

    @Override
    public UserScoresDO getCurrentUserScores(Long userId) {
        return userScoresMapper.selectCurrentByUserId(userId);
    }

    @Override
    public List<UserScoresDO> getUserScoresList(Long userId) {
        return userScoresMapper.selectListByUserId(userId);
    }

    @Override
    public List<UserScoresDO> getCurrentUserScoresList(List<Long> userIds) {
        return userScoresMapper.selectCurrentListByUserIds(userIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setCurrentUserScores(Long userId, Long scoresId) {
        // 校验成绩记录存在且属于该用户
        UserScoresDO userScores = getUserScores(scoresId);
        if (userScores == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.USER_NOT_EXISTS);
        }
        if (!userScores.getUserId().equals(userId)) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.USER_NOT_EXISTS);
        }
        
        // 先将该用户的所有成绩设置为非当前
        userScoresMapper.updateAllToNonCurrent(userId);
        
        // 设置指定成绩为当前
        userScores.setIsCurrent(true);
        userScores.setUpdateTime(LocalDateTime.now());
        userScoresMapper.updateById(userScores);
    }

    @Override
    public List<UserScoresDO> getUserScoresByProvinceAndYear(String province, Integer examYear) {
        return userScoresMapper.selectListByProvinceAndYear(province, examYear);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean migrateUserScoresFromSystemUser(Long userId) {
        try {
            // 获取用户信息
            AdminUserDO user = adminUserService.getUser(userId);
            if (user == null) {
                log.warn("User not found for migration: {}", userId);
                return false;
            }
            
            // 检查是否已有成绩记录
            UserScoresDO existingScores = getCurrentUserScores(userId);
            if (existingScores != null) {
                log.info("User {} already has scores record, skipping migration", userId);
                return true;
            }
            
            // 检查是否有成绩数据需要迁移
            if (user.getProvince() == null && user.getGrade() == null && 
                user.getFirstSubject() == null && user.getSecondSubject() == null &&
                user.getScore() == null && user.getRanking() == null &&
                user.getRankingRange() == null && user.getTypeName() == null &&
                user.getMinScore() == null && user.getMaxScore() == null) {
                log.info("User {} has no scores data to migrate", userId);
                return true;
            }
            
            // 创建成绩记录
            UserScoresDO userScores = UserScoresDO.builder()
                    .userId(userId)
                    .province(user.getProvince())
                    .grade(user.getGrade())
                    .firstSubject(user.getFirstSubject())
                    .secondSubject(user.getSecondSubject())
                    .score(user.getScore() != null ? BigDecimal.valueOf(user.getScore()) : null)
                    .ranking(user.getRanking())
                    .rankingRange(user.getRankingRange())
                    .typeName(user.getTypeName())
                    .minScore(user.getMinScore() != null ? BigDecimal.valueOf(user.getMinScore()) : null)
                    .maxScore(user.getMaxScore() != null ? BigDecimal.valueOf(user.getMaxScore()) : null)
                    .examYear(LocalDateTime.now().getYear()) // 默认设置为当前年份
                    .isCurrent(true)
                    .remark("从system_users表迁移的数据，迁移时间：" + LocalDateTime.now())
                    .build();
            
            createUserScores(userScores);
            
            log.info("Successfully migrated scores data for user {}", userId);
            return true;
            
        } catch (Exception e) {
            log.error("Failed to migrate scores data for user {}", userId, e);
            return false;
        }
    }

    @Override
    public void updateCurrentScoreRanking(Long userId, String ranking, String rankingRange) {
        // 获取用户当前的成绩记录
        UserScoresDO currentScore = userScoresMapper.selectCurrentByUserId(userId);
        if (currentScore == null) {
            log.warn("No current score record found for user ID {}", userId);
            return;
        }

        // 更新排名信息
        UserScoresDO updateObj = new UserScoresDO();
        updateObj.setId(currentScore.getId());
        updateObj.setRanking(ranking);
        updateObj.setRankingRange(rankingRange);
        updateObj.setUpdateTime(LocalDateTime.now());

        userScoresMapper.updateById(updateObj);
        log.info("Updated ranking for user ID {} score record ID {}: ranking={}, rankingRange={}", 
                userId, currentScore.getId(), ranking, rankingRange);
    }

    private void validateUserScoresExists(Long id) {
        if (userScoresMapper.selectById(id) == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.USER_NOT_EXISTS);
        }
    }

    // ==================== 控制器相关方法实现 ====================

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createUserScore(@Valid UserScoresSaveReqVO createReqVO) {
        // 转换为 DO 对象
        UserScoresDO userScores = BeanUtils.toBean(createReqVO, UserScoresDO.class);
        userScores.setCreateTime(LocalDateTime.now());
        userScores.setUpdateTime(LocalDateTime.now());
        
        // 如果设置为当前记录，需要先将该用户的其他记录设置为非当前
        if (Boolean.TRUE.equals(userScores.getIsCurrent())) {
            userScoresMapper.updateCurrentToFalse(userScores.getUserId());
        }
        
        // 插入记录
        userScoresMapper.insert(userScores);
        return userScores.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUserScore(@Valid UserScoresSaveReqVO updateReqVO) {
        // 校验存在
        validateUserScoresExists(updateReqVO.getId());
        
        // 转换为 DO 对象
        UserScoresDO updateObj = BeanUtils.toBean(updateReqVO, UserScoresDO.class);
        updateObj.setUpdateTime(LocalDateTime.now());
        
        // 如果设置为当前记录，需要先将该用户的其他记录设置为非当前
        if (Boolean.TRUE.equals(updateObj.getIsCurrent())) {
            userScoresMapper.updateCurrentToFalse(updateObj.getUserId());
        }
        
        // 更新记录
        userScoresMapper.updateById(updateObj);
    }

    @Override
    public void deleteUserScore(Long id) {
        // 校验存在
        validateUserScoresExists(id);
        // 删除
        userScoresMapper.deleteById(id);
    }

    @Override
    public UserScoresDO getUserScore(Long id) {
        return userScoresMapper.selectById(id);
    }

    @Override
    public PageResult<UserScoresDO> getUserScorePage(UserScoresPageReqVO pageReqVO) {
        return userScoresMapper.selectPage(pageReqVO);
    }

    @Override
    public List<UserScoresDO> getUserScoreList(UserScoresExportReqVO exportReqVO) {
        return userScoresMapper.selectList(exportReqVO);
    }

    @Override
    public List<UserScoresDO> getUserScoresByUserId(Long userId) {
        return userScoresMapper.selectByUserId(userId);
    }

    @Override
    public UserScoresDO getCurrentUserScore(Long userId) {
        return userScoresMapper.selectCurrentByUserId(userId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void setCurrentUserScore(Long id) {
        // 校验记录存在
        UserScoresDO userScore = userScoresMapper.selectById(id);
        if (userScore == null) {
            throw ServiceExceptionUtil.exception(ErrorCodeConstants.USER_NOT_EXISTS);
        }
        
        // 先将该用户的所有记录设置为非当前
        userScoresMapper.updateCurrentToFalse(userScore.getUserId());
        
        // 设置指定记录为当前
        UserScoresDO updateObj = new UserScoresDO();
        updateObj.setId(id);
        updateObj.setIsCurrent(true);
        updateObj.setUpdateTime(LocalDateTime.now());
        userScoresMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void migrateScoresFromUsers() {
        int successCount = 0;
        int failCount = 0;
        int pageNo = 1;
        int pageSize = 100;
        
        while (true) {
            // 分页获取用户列表
            UserPageReqVO pageReqVO = new UserPageReqVO();
            pageReqVO.setPageNo(pageNo);
            pageReqVO.setPageSize(pageSize);
            
            PageResult<AdminUserDO> pageResult = adminUserService.getUserPage(pageReqVO);
            List<AdminUserDO> users = pageResult.getList();
            
            if (users.isEmpty()) {
                break; // 没有更多用户了
            }
            
            for (AdminUserDO user : users) {
                try {
                    // 检查是否已经存在该用户的分数记录
                    UserScoresDO existingScore = userScoresMapper.selectCurrentByUserId(user.getId());
                    if (existingScore != null) {
                        log.info("User {} already has score record, skipping migration", user.getId());
                        continue;
                    }
                    
                    // 迁移用户分数数据
                    boolean success = migrateUserScoresFromSystemUser(user.getId());
                    if (success) {
                        successCount++;
                    } else {
                        failCount++;
                    }
                } catch (Exception e) {
                    log.error("Failed to migrate user {} scores", user.getId(), e);
                    failCount++;
                }
            }
            
            // 如果当前页的用户数量小于页大小，说明已经是最后一页
            if (users.size() < pageSize) {
                break;
            }
            
            pageNo++;
        }
        
        log.info("Migration completed. Success: {}, Failed: {}", successCount, failCount);
    }

}